﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Net.Browser;
using System.IO;
using System.Text;
using System.Windows.Browser;
using System.Collections.Generic;
using System.Windows.Threading;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.IO.IsolatedStorage;

namespace PicasaManager
{
    public class GAdapter : oAuthBase
    {
        /* Access token retrieval guide
         * 
         *1) POST  https://www.google.com/accounts/OAuthGetRequestToken
         * with
         * authorization params: oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_signature, oauth_timestamp, oauth_callback, oauth_version
         * post params:  scope,xoauth_displayname
         * * signature with oauth_token_secret(blank) and oauth_consumer_secret
         * 
         * you get a oauth_token & oauth_token_secret
         * 
         * 2) GET https://www.google.com/accounts/OAuthAuthorizeToken
         * 
         * get params: oauth_token(you got from step 1)
         * 
         * you get a oauth_token=CKF50YzIHxCT85KMAg&oauth_verifier=fERNOO3NfWph90CPCeIutmFA
         * 
         * 3) POST https://www.google.com/accounts/OAuthGetAccessToken
         * with
         * Content-Type: application/x-www-form-urlencoded
         * authorization params: oauth_consumer_key, oauth_token(from step 2),oauth_verifier(from step 2), oauth_signature_method, oauth_signature, oauth_timestamp, oauth_nonce, oauth_version
         * signature with oauth_token_secret(from step1) and oauth_consumer_secret
         * 
         * 
         * you get oauth_token & oauth_token_secret  which you memorize
         * 
         * 4)You request or post something using the tokens
         * 
         * authorization params: oauth_token, oauth_signature_method, oauth_signature, oauth_consumer_key, oauth_timestamp, oauth_nonce, oauth_version
         * 
         * you get your data
         */
        public const string REQUEST_TOKEN_URL = "https://www.google.com/accounts/OAuthGetRequestToken";
        public const string ACCESS_TOKEN_URL = "https://www.google.com/accounts/OAuthGetAccessToken";
        public const string SIGNATURE_METHOD = "HMAC-SHA1";
        public const string CALLBACK = "http://localhost:9999/Success.htm";


        public const string CONSUMER_KEY = "anonymous";
        public const string CONSUMER_SECRET = "anonymous";

        public const string CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded";
        public const string CONTENT_TYPE_XML = "application/atom+xml";

        public static string Token
        {
            get
            {
                if (IsolatedStorageSettings.SiteSettings.Contains("token"))
                {
                    return (string)IsolatedStorageSettings.SiteSettings["token"];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                IsolatedStorageSettings.SiteSettings["token"] = value;
                IsolatedStorageSettings.SiteSettings.Save();
            }
        }
        public static string TokenSecret
        {
            get
            {
                if (IsolatedStorageSettings.SiteSettings.Contains("token_secret"))
                {
                    return (string)IsolatedStorageSettings.SiteSettings["token_secret"];
                }
                else
                {
                    return null;
                }
            }
            set
            {
                IsolatedStorageSettings.SiteSettings["token_secret"] = value;
                IsolatedStorageSettings.SiteSettings.Save();
            }
        }

        public GAdapter()
        {
            WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
            WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
        }

        Dispatcher _uiDispatcher;

        private void GetRequestToken(string scope,Action<Dictionary<string,string>> response)
        {
            WebClientHelper wch = new WebClientHelper(null);
            Dictionary<string, string> postParams = new Dictionary<string, string>();
            postParams.Add("scope", scope);

            string postData = "scope=" + UrlEncode(scope);

            var _webRequest = GetWebRequest(CALLBACK, postParams, null, null, null, REQUEST_TOKEN_URL, "POST", CONSUMER_KEY, CONSUMER_SECRET, CONTENT_TYPE_URLENCODED);

            wch.RequestCompleted += (sender, e) =>
                {
                    Dictionary<string, string> responses;
                    if (e.Response != null)
                    {
                        StreamReader sr = new StreamReader(e.Response);
                        responses = GetQueryParameters(HttpUtility.UrlDecode(sr.ReadToEnd()));

                        //string token = responses["oauth_token"];
                        //string token_secret = responses["oauth_token_secret"];

                        response.Invoke(responses);
                    }
                };
            wch.SendRequest(_webRequest, postData);
        }

        private void AuthorizeToken(string token, Action<Dictionary<string, string>> response)
        {
              _uiDispatcher.BeginInvoke(() =>
                        {
                            OOBLogin login = new OOBLogin("https://www.google.com/accounts/OAuthAuthorizeToken?oauth_token=" + UrlEncode(token) + "&hd=default");
                            login.Closed += (sender, e) =>
                                {
                                    string tokenString = ((OOBLogin)sender).SessionString;
                                    if (string.IsNullOrEmpty(tokenString) == false)
                                    {
                                        Dictionary<string, string> responses = GetQueryParameters(tokenString.Remove(0, tokenString.IndexOf("?") + 1));

                                        //string oAuthVerifier = responses["oauth_verifier"];
                                        //string oAuthToken = responses["oauth_token"];
                                        
                                        response.Invoke(responses);
                                    }
                                };
                            login.Show();
                        });
        }

        private void GetAccessToken(string authorizedToken, string verifier, string tokenSecret, Action<Dictionary<string, string>> response)
        {
            WebClientHelper wch = new WebClientHelper(null);
            WebRequest _webRequest = GetWebRequest(null, null, authorizedToken, verifier, tokenSecret, ACCESS_TOKEN_URL, "POST", CONSUMER_KEY, CONSUMER_SECRET, CONTENT_TYPE_URLENCODED);

            wch.RequestCompleted += (sender, e) =>
                {
                    Dictionary<string, string> responses;
                    if (e.Response != null)
                    {
                        StreamReader sr = new StreamReader(e.Response);
                        responses = GetQueryParameters(HttpUtility.UrlDecode(sr.ReadToEnd()));

                        //string token = responses["oauth_token"];
                        //string token_secret = responses["oauth_token_secret"];

                        response.Invoke(responses);
                    }
                };
            wch.SendRequest(_webRequest, null);
        }

        public void LoginAsync(string scope, Action<bool> loginCompletedCallback)
        {
            //IsolatedStorageSettings.SiteSettings.Clear();
            //IsolatedStorageSettings.SiteSettings.Save();
            if (Token == null || TokenSecret == null)
            {
                GetRequestToken(scope, (requestResponse) =>
                    {
                        AuthorizeToken(requestResponse["oauth_token"], (authorizeResponse) =>
                            {
                                GetAccessToken(authorizeResponse["oauth_token"], authorizeResponse["oauth_verifier"], requestResponse["oauth_token_secret"], (accessResponse) =>
                                    {
                                        string token = accessResponse["oauth_token"];
                                        string token_secret = accessResponse["oauth_token_secret"];
                                        Token = token;
                                        TokenSecret = token_secret;
                                        if (loginCompletedCallback != null)
                                        {
                                            loginCompletedCallback.Invoke(true);
                                        }
                                    });
                            });
                    });
            }
            else
            {
                if (loginCompletedCallback != null)
                {
                    loginCompletedCallback.Invoke(true);
                }
            }
        }


        public void RequestUserWithAlbums(string user, Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/user/"+user;

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
                {
                    //byte[] bytes = new byte[e.Response.Length];
                    //e.Response.Position = 0;
                    //e.Response.Read(bytes, 0, (int)e.Response.Length);
                    //string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                    if (callback != null)
                    {
                        callback.Invoke(e.Response);
                    }
                };
            wch.SendRequest(_webRequest, null);
        }

        public void RequestAlbum(string userid, string albumId, Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/user/" + userid + "/albumid/" + albumId;

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
            {
                //byte[] bytes = new byte[e.Response.Length];
                //e.Response.Position = 0;
                //e.Response.Read(bytes, 0, (int)e.Response.Length);
                //string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                if (callback != null)
                {
                    callback.Invoke(e.Response);
                }
            };
            wch.SendRequest(_webRequest, null);
        }

        public void RequestFeatured(int max_results,Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/featured?max-results="+max_results;

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
            {
                byte[] bytes = new byte[e.Response.Length];
                e.Response.Position = 0;
                e.Response.Read(bytes, 0, (int)e.Response.Length);
                string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                if (callback != null)
                {
                    callback.Invoke(e.Response);
                }
            };
            wch.SendRequest(_webRequest, null);
        }

        public void RequestContacts(string userid,Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/user/"+userid+"/contacts?kind=user";

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
            {
                byte[] bytes = new byte[e.Response.Length];
                e.Response.Position = 0;
                e.Response.Read(bytes, 0, (int)e.Response.Length);
                string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                if (callback != null)
                {
                    callback.Invoke(e.Response);
                }
            };
            wch.SendRequest(_webRequest, null);
        }

        public void RequestPhoto(string userId, string albumId, string photoId, Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/user/" + userId + "/albumid/" + albumId + "/photoid/" + photoId;    

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
            {
                byte[] bytes = new byte[e.Response.Length];
                e.Response.Position = 0;
                e.Response.Read(bytes, 0, (int)e.Response.Length);
                string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                if (callback != null)
                {
                    callback.Invoke(e.Response);
                }
            };
            wch.SendRequest(_webRequest, null);
        }

        public void RequestSearch(string searchTerm, Action<Stream> callback)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/all?kind=photo&q="+searchTerm;

            WebRequest _webRequest = GetWebRequest(null, null, Token, null, TokenSecret, uri, "GET", CONSUMER_KEY, CONSUMER_SECRET, null);

            WebClientHelper wch = new WebClientHelper(null);
            wch.RequestCompleted += (sender, e) =>
            {
                byte[] bytes = new byte[e.Response.Length];
                e.Response.Position = 0;
                e.Response.Read(bytes, 0, (int)e.Response.Length);
                string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());
                if (callback != null)
                {
                    callback.Invoke(e.Response);
                }
            };
            wch.SendRequest(_webRequest, null);
        }

        


        private void CreateAlbum(string token, string token_secret)
        {
            string uri = "http://picasaweb.google.com/data/feed/api/user/default";
            string timestamp = GenerateTimeStamp();
            string nonce = GenerateNonce();
            string normalizedUrl = string.Empty;
            string querystring = string.Empty;
            Verifier = null;
            string sig = this.GenerateSignature(new Uri(uri), "anonymous", "anonymous", token, null, token_secret, "POST", timestamp, nonce, null, null, out normalizedUrl, out querystring);

            WebRequest _webRequest = WebRequest.Create(uri);

            _webRequest.Method = "POST";
            _webRequest.Headers["Authorization"] = "OAuth "
                + "oauth_version=\"" + "1.0" + "\""
                + ", oauth_nonce=\"" + nonce + "\""
                + ", oauth_timestamp=\"" + timestamp + "\""
                + ", oauth_consumer_key=\"" + "anonymous" + "\""
                + ", oauth_token=\"" + token + "\""
                + ", oauth_signature_method=\"" + "HMAC-SHA1" + "\""
                + ", oauth_signature=\"" + sig + "\"";//"OAuth oauth_nonce=\"" + nonce + "\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"" + timestamp + "\", oauth_consumer_key=\"" + "anonymous" + "\", oauth_token=\"" + UrlEncode(Token) + "\", oauth_signature=\"" + UrlEncode(sig) + "\", oauth_version=\"1.0\"";
            //_webRequest.ContentType = "application/x-www-form-urlencoded";
            _webRequest.ContentType = "application/atom+xml";
            string postInfo = @"<entry xmlns='http://www.w3.org/2005/Atom'
    xmlns:media='http://search.yahoo.com/mrss/'
    xmlns:gphoto='http://schemas.google.com/photos/2007'>
  <title type='text'>Trip To Italy</title>
  <summary type='text'>This was the recent trip I took to Italy.</summary>
  <gphoto:location>Italy</gphoto:location>
  <gphoto:access>public</gphoto:access>
  <gphoto:timestamp>1152255600000</gphoto:timestamp>
  <media:group>
    <media:keywords>italy, vacation</media:keywords>
  </media:group>
  <category scheme='http://schemas.google.com/g/2005#kind'
    term='http://schemas.google.com/photos/2007#album'></category>
</entry>";
            //WebClientHelper wch = new WebClientHelper(null);
            //wch.RequestCompleted += new EventHandler<RequestCompletedEventArgs>(GetCalendarCompleted);
            //wch.SendRequest(_webRequest, postInfo);
        }

        //void GetCalendarCompleted(object sender, RequestCompletedEventArgs e)
        //{
        //    byte[] bytes = new byte[e.Response.Length];
        //    e.Response.Position = 0;
        //    e.Response.Read(bytes, 0, (int)e.Response.Length);
        //    string data = Encoding.UTF8.GetString(bytes, 0, bytes.Count());

        //    e.Response.Position = 0;

        //    XmlReader responseReader = XmlReader.Create(e.Response);
        //    SyndicationFeed feed = SyndicationFeed.Load(responseReader);
        //}
     
        private WebRequest GetWebRequest(string callback, Dictionary<string, string> otherParams, string token, string verifier, string tokenSecret, string requestUrl, string method, string consumerKey, string consumerSecret, string contentType)
        {
            string outUrl = "";
            string querystring = "";

            string timestamp = this.GenerateTimeStamp();
            string nonce = this.GenerateNonce();

            string sig = this.GenerateSignature(new Uri(requestUrl), consumerKey, consumerSecret, token, verifier, tokenSecret, method, timestamp, nonce, callback, otherParams, out outUrl, out querystring);

            WebRequest _webRequest = WebRequest.Create(requestUrl);
            _webRequest.Method = method;
            if (contentType != null)
            {
                _webRequest.ContentType = contentType;
            }

            _webRequest.Headers["Authorization"] = "OAuth "
               + "oauth_version=\"1.0\""
               + ", oauth_nonce=\"" + nonce + "\""
               + ", oauth_timestamp=\"" + timestamp + "\""
               + ", oauth_consumer_key=\"" + "anonymous" + "\""
               + (!string.IsNullOrEmpty(callback) ? ", oauth_callback=\"" + UrlEncode(callback) + "\"" : "")
                + (!string.IsNullOrEmpty(verifier) ? ", oauth_verifier=\"" + UrlEncode(verifier) + "\"" : "")
               + (!string.IsNullOrEmpty(token) ? (", oauth_token=\"" + token + "\"") : "")
               + ", oauth_signature_method=\"" + "HMAC-SHA1" + "\""
               + ", oauth_signature=\"" + UrlEncode(sig) + "\"";
            return _webRequest;
        }

        private static Dictionary<string, string> GetQueryParameters(string response)
        {
            Dictionary<string, string> responses = new Dictionary<string, string>();

            string[] parts = response.Split(new char[] { '&' });
            foreach (string part in parts)
            {
                string[] keyvalue = part.Split(new char[] { '=' });
                responses.Add(keyvalue[0], keyvalue[1]);
            }
            return responses;
        }


    }
}


